1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.webmacro.util;
24
25 import org.webmacro.*;
26 import org.webmacro.servlet.*;
27 import org.webmacro.engine.*;
28
29
30 import javax.servlet.Servlet;
31 import javax.servlet.ServletException;
32 import javax.servlet.http.HttpServletRequest;
33 import javax.servlet.http.HttpServletResponse;
34 import java.io.FileOutputStream;
35 import java.io.InputStream;
36 import java.io.InputStreamReader;
37 import java.io.OutputStream;
38
39
40 /***
41 * WMEval encapsulates an instance of WebMacro for reuse in any java application.
42 * <p>
43 * Its main benefit are a number of convenience methods for evaluating a template
44 * and directing output either to a supplied output stream or to a file.
45 * <p>
46 * It can parse a single template stream and then evaluate that template
47 * over a number of different contexts. And, it can maintain a single context
48 * and evaluate different templates over the same context. Each time a context
49 * or a template is provided, it is retained as state.
50 * <p>
51 * The context can therefore be preserved over multiple "writes" of different
52 * templates.
53 * <p>
54 * The template stream can be any text stream but is often a rule stream containing
55 * wm script directives.
56 * <p>
57 * This helper class is useful for evaluating WebMacro templates for which
58 * flexibility in managing the evaluation options is key.
59 * @author Lane Sharman
60 * @version 3.0
61 */
62 public class WMEval
63 {
64
65
66
67
68 private WebMacro wm;
69 private Log log;
70 private Template currentTemplate;
71 private OutputStream out = System.out;
72 private Context context;
73 /***
74 * If an output file is not specified as an argument, it
75 * must be found in the context under this key.
76 */
77 public static final String outputContextKey = "OutputFileName";
78
79
80 /***
81 * The constructor for WebMacro decorator in a servlet context.
82 */
83 public WMEval (Servlet servlet)
84 {
85
86 try
87 {
88 if (servlet == null)
89 wm = new WM();
90 else
91 wm = new WM(servlet);
92 context = wm.getContext();
93 log = wm.getBroker().getBrokerLog();
94 }
95 catch (Exception e)
96 {
97 e.printStackTrace(System.err);
98 throw new IllegalStateException(e.toString());
99 }
100 }
101
102 public WMEval ()
103 {
104
105 try
106 {
107 wm = new WM();
108 context = wm.getContext();
109 }
110 catch (Exception e)
111 {
112 e.printStackTrace(System.err);
113 throw new IllegalStateException(e.toString());
114 }
115 }
116
117 /***
118 * Return the settings associated with this WebMacro instance.
119 */
120 public Settings getSettings()
121 {
122 return wm.getBroker().getSettings();
123 }
124
125 /***
126 * Return the log associated with this instance of WMEval.
127 */
128 public Log getLog()
129 {
130 return this.log;
131 }
132
133
134
135 /***
136 * Initializes WMEval so that it can perform currentTemplate evaluation
137 * on multiple contexts. Init parses the currentTemplate supplied.
138 * <p>
139 * The argument to init() is the currentTemplate as a stream allowing the currentTemplate
140 * to come from pretty much anywhere such as a url, a file, or a db field.
141 * <p>
142 * Care must be given to the fact that in parsing the currentTemplate, th current vm is able
143 * to resolve locations of other currentTemplates referenced within the supplied currentTemplate.
144 * <p>
145 * Note, once this is complete, the parsed currentTemplate can be applied to successive
146 * new object contexts. In other words, the application context
147 * can assert new objects for currentTemplate application and remove others.
148 * @param template The stream containing the top-level, unparsed currentTemplate.
149 *
150 */
151 public Template init (InputStream template) throws Exception
152 {
153
154 Template t = new StreamTemplate(wm.getBroker(), new InputStreamReader(template));
155 t.parse();
156 this.currentTemplate = t;
157 return t;
158 }
159
160
161 public void error (String msg, Exception e)
162 {
163 wm.getLog("ERROR").error(msg, e);
164 }
165
166 /***
167 * Provides for a new context to be established.
168 */
169 public Context getNewContext ()
170 {
171 Context c = wm.getContext();
172 this.context = c;
173 return c;
174 }
175
176 public WebContext getNewContext (HttpServletRequest req, HttpServletResponse resp)
177 {
178 WebContext c = wm.getWebContext(req, resp);
179 this.context = c;
180 return c;
181 }
182
183 /***
184 * Gets the current context.
185 */
186 public Context getCurrentContext ()
187 {
188 return this.context;
189 }
190
191 /***
192 * Gets the current template.
193 */
194 public Template getCurrentTemplate()
195 {
196 return this.currentTemplate;
197 }
198
199 /***
200 * A convenience method to find and parse a template in the local template path.
201 */
202 public Template parseLocalTemplate (String templateName) throws Exception
203 {
204 Template t = wm.getTemplate(templateName);
205 this.currentTemplate = t;
206 return t;
207 }
208
209 /***
210 * Supplies the parsed currentTemplate directly.
211 * @param parsedTemplate The currentTemplate parsed possibly from a previous run.
212 */
213 public void setCurrentTemplate (Template parsedTemplate)
214 {
215 this.currentTemplate = parsedTemplate;
216 }
217
218 /***
219 * Supplies a context to be parsed currentTemplate directly.
220 * @param c The context to be used for the evaluation.
221 */
222 public void setCurrentContext (Context c)
223 {
224 this.context = c;
225 }
226
227 /***
228 * Sets the output stream to be different than the default, System.out.
229 * @param out The new output stream for any output during currentTemplate evaluation.
230 */
231 public void setOutputStream (OutputStream out)
232 {
233 this.out = out;
234 }
235
236 /***
237 * Evaluates the context of this instance and the instance's
238 * current template and current output stream using UTF8.
239 */
240 public void eval() throws Exception
241 {
242 eval(context, currentTemplate);
243 }
244
245
246 /***
247 * Evaluate the context supplied against the current template.
248 * @param context The WebMacro context.
249 */
250 public String eval (Context context) throws Exception
251 {
252 return eval(context, currentTemplate);
253 }
254
255 /***
256 * Evaluates the string template against the current context
257 * and returns the value. If an output stream is specified, the value
258 * is written out as well to this stream.
259 * @param templateName The name of the template.
260 * @param out An optional output stream.
261 * @return The output from the evaluated template
262 */
263 public String eval (Context context, String templateName, OutputStream out) throws Exception
264 {
265 return eval(context, templateName, out, null);
266 }
267
268 /***
269 * Evaluates the string template against the current context
270 * and returns the value.
271 * @param templateName The name of the template.
272 * @return The output from the evaluated template
273 */
274 public String eval (String templateName) throws Exception
275 {
276 return eval(context, templateName, null, null);
277 }
278
279 /***
280 * Evaluates the string template against a new context and writes
281 * it to the http Response output stream using the proper encoding.
282 * <p>
283 * This is an exceptionally useful method for a servlet to use to
284 * write out a template.
285 * <p>
286 * @param context The WM context to use.
287 * @param templateName The name of the template.
288 * @param resp The servlet response from which the encoding will be derived.
289 * @return The output from the evaluated template.
290 */
291 public String eval (WebContext context, String templateName,
292 HttpServletResponse resp) throws ServletException
293 {
294 String value = null;
295 try
296 {
297 resp.setContentType("text/html");
298 String encoding = wm.getConfig(WMConstants.TEMPLATE_OUTPUT_ENCODING);
299 if (encoding == null)
300 {
301 encoding = resp.getCharacterEncoding();
302 }
303 value = eval(context, templateName, resp.getOutputStream(), encoding);
304 }
305 catch (Exception e)
306 {
307 e.printStackTrace(System.err);
308 throw new ServletException(e.toString());
309 }
310 return value;
311 }
312
313 /***
314 * Evaluate the supplied context and template and return the result as a
315 * as a string.
316 */
317 public String eval (Context context, Template template) throws Exception
318 {
319 return template.evaluateAsString(context);
320 }
321
322 /***
323 * Evaluates the context using a file template sending the output to a disk file.
324 * <p>
325 * This method is the preferred method when an output stream is to be written
326 * as well as the value of the string is to be returned.
327 * @param context The context to use.
328 * @param templateName The input template file in the resource path.
329 * @param out The output stream. If null, an attempt will be
330 * made to locate the outputstream in the context using the output stream key if
331 * in the context. If no output stream can be resolved, the method does not
332 * throw an exception.
333 * @param encoding If null, the platform's encoding will be used.
334 * @return The output from the evaluation of the template.
335 */
336 public String eval (Context context, String templateName,
337 OutputStream out, String encoding) throws Exception
338 {
339 Template t = wm.getTemplate(templateName);
340 String value = t.evaluateAsString(context);
341
342 if (out == null)
343 {
344 String outputFileName = (String) context.get(outputContextKey);
345 if (outputFileName != null)
346 {
347 out = new FileOutputStream(outputFileName);
348 }
349 }
350 if (out != null)
351 {
352 if (encoding == null)
353 {
354 out.write(value.getBytes());
355 }
356 else {
357 out.write(value.getBytes(encoding));
358 }
359 out.close();
360 }
361 this.currentTemplate = t;
362 this.context = context;
363 return value;
364 }
365
366 /***
367 * Evaluates the current context for the input file and writes it to the output file.
368 */
369 public String eval (Context context, String templateName, String outputFileName, boolean append, String encoding) throws Exception
370 {
371 OutputStream out = new FileOutputStream(outputFileName, append);
372 return eval(context, templateName, out, encoding);
373 }
374
375
376 /***
377 * Free up resources when no longer needed.
378 */
379 public void destroy ()
380 {
381 wm = null;
382 currentTemplate = null;
383 }
384 }